# ICEMGenerator - 高效的ICEM CFD网格划分Replay Script生成工具
# 模块： 全局控制模块，实现对整个网格划分过程的全局控制，并最终生成完整的网格划分Replay Script
# 作者： weixc
# 邮箱： 12028045 [at] zju.edu.cn
# 项目主页： https://gitee.com/weixinchong/icemgenerator

import os
from .point import Point
from .curve import Curve
from .surface import Surface
from .body import Body
from .part import Part
from .block import Block
from .mesh import TetraMesh, update_all, update_part_mesh, gen_mesh_from_block, replay_save_mesh

fluent_dir = 'C:/Program Files/ANSYS Inc/v191/icemcfd/win64_amd/icemcfd/output-interfaces/fluent6.exe'

def init_all_Id(startId: int):
    '''设置点、线、面的起始编号，应在开始创建点线面之前调用
    :param startId: 起始编号，第一个点、线、面均从startId开始编号；未定义时，起始编号均为0'''
    Point.init_pId(startId)
    Curve.init_cId(startId)
    Surface.init_sId(startId)

def update_fluent_dir(fdir: str = 'C:/Program Files/ANSYS Inc/v191/icemcfd/win64_amd/icemcfd/output-interfaces/fluent6.exe'):
    '''更改Fluent应用程序的工作路径
    :param fdir: Fluent应用程序的绝对路径'''
    fluent_dir = fdir

def replay_geo(cut_surfaces_priority: int = 0) -> str:
    '''生成几何模型创建部分的Replay Script
    :param cut_surfaces_priority: 需要切割的面在创建时的优先顺序:
        取0时: 按原有创建面的顺序进行创建；
        取1时: 将这些面放在其他面之前进行创建，相当于先切割；
        取-1时: 将这些面放在其他面之后进行创建，相当于后切割
    :return: 生成的Replay Script'''
    text = Point.members_replay()  #创建点
    text += '\n' + Curve.members_replay()  #创建线
    if Curve.members_replay(assisted = True) != '':
        text += '\n' + Curve.members_replay(assisted = True)  #创建辅助线
    text += '\n' + Surface.members_replay(cut_surfaces_priority)  #创建面及切割面
    if len(Body.final_members) > 0:
        text += '\n' + Body.final_members_replay()  #创建体
    text += '\n' + Part.members_create_replay()  #创建Part
    return text

def replay_all(directory: str, fName: str, max_element_size: float = 1.0, gen_mesh: bool = True, 
               save_mesh: bool = True, cut_surfaces_priority: int = 0, repair_geo: bool = True, scale: float = 1) -> str:
    '''生成完整的网格划分Replay Script
    :param directory: 网格的工作路径
    :param fName: 导出的msh网格文件名
    :param max_element_size: 全局网格最大尺寸
    :param gen_mesh: 是否生成网格，当自动完成网格预处理之后，需要手动调整网格时，可设定为False
    :param save_mesh: 是否导出msh网格，当gen_mesh为False时，save_mesh无论取何值都不会导出msh
    :param cut_surfaces_priority: 需要切割的面在创建时的优先顺序:
        取0时: 按原有创建面的顺序进行创建；
        取1时: 将这些面放在其他面之前进行创建，相当于先切割；
        取-1时: 将这些面放在其他面之后进行创建，相当于后切割
    :param repair_geo: 是否进行修复几何操作
    :param scale: 网格的比例尺'''
    if not os.path.exists(directory):
        os.makedirs(directory)
    text = Point.members_replay()  #创建点
    text += '\n' + Curve.members_replay()  #创建线
    if Curve.members_replay(assisted = True) != '':
        text += '\n' + Curve.members_replay(assisted = True)  #创建辅助线
    text += '\n' + Surface.members_replay(cut_surfaces_priority)  #创建面及切割面
    if repair_geo:
        text += '\nic_build_topo %g -angle 30 -filter_points -filter_curves -create_interior -no_concat GEOM ORFN' % Point.get_repair_tolerance()  #修复几何
    if len(Body.final_members) > 0:
        text += '\n' + Body.final_members_replay()  #创建体
    text += '\n' + Part.members_create_replay()  #创建Part
    mesh_already_gen = False
    if len(Block.members) > 0:
        text += Block.members_replay()  #创建Block
        mesh_already_gen = True
    text += '\n' + update_all(max_element_size)
    if TetraMesh.applied:
        text += '\n' + TetraMesh.replay()  #创建四面体网格
        mesh_already_gen = True
    text += '\nic_chdir %s' % directory  #切换至网格的输出路径
    text += '\n' + Part.members_apply_bc_replay(fName)  #给定各个Part的边界条件
    if gen_mesh and mesh_already_gen:
        if len(Block.members) > 0:
            text += '\n' + gen_mesh_from_block(fName)  #由Block创建Mesh
        if save_mesh:
            text += '\n' + replay_save_mesh(directory, fName, fluent_dir, scale)
    return text

def clear_all():
    '''清除所有网格信息，包括几何、Part和Block'''
    Point.curr_pId = 0
    Point.members = []
    Curve.curr_cId = 0
    Curve.members = []
    Surface.curr_sId = 0
    Surface.curr_tmpId = 0
    Surface.members = []
    Surface.members_cut = []
    Body.members = []
    Body.final_members = []
    Part.members = []
    Part.parted_objects = []
    Block.members = []
    TetraMesh.applied = False
    TetraMesh.mode = 'all_geo'
    TetraMesh.from_part = None
    TetraMesh.script = ''
    TetraMesh.periodicity_script = ''